import socket
import threading
import queue
import logging


# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')


class ChatServer:
    def __init__(self, host="127.0.0.1", port=8887):
        self.host = host
        self.port = port
        self.server_socket = None
        self.client_socket = None
        self.input_queue = queue.Queue()  # 用于线程安全的输入

    def start(self):
        try:
            self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.server_socket.bind((self.host, self.port))
            self.server_socket.listen(5)
            logging.info(f"Server started on {self.host}:{self.port}")

            while True:
                self.client_socket, client_addr = self.server_socket.accept()
                logging.info(f"Accepted connection from {client_addr}")

                client_thread = threading.Thread(target=self.handle_client, args=(self.client_socket, client_addr))
                client_thread.start()

        except Exception as e:
            logging.error(f"Server error: {e}")
        finally:
            if self.server_socket:
                self.server_socket.close()

    def handle_client(self, client_socket, client_addr):
        try:
            # 设置超时时间，防止阻塞
            # client_socket.settimeout(10)
            client_auth = client_socket.recv(1024).decode('utf-8', 'ignore')
            if not client_auth.startswith("auth:"):  # 简单的身份验证
                client_socket.send(b"Authentication failed.")
                return
            logging.info(f"Client {client_addr} authenticated.")

            while True:
                try:
                    message = self.input_queue.get(timeout=1)  # 线程安全地获取输入
                    if message == "bye":
                        break
                    client_socket.send(message.encode('utf-8'))
                    logging.info(f"Message sent to {client_addr}: {message}")
                except queue.Empty:
                    # 没有新消息时继续等待
                    continue

                response = client_socket.recv(1024)
                if not response:
                    break
                else:
                    response_text = response.decode('utf-8', 'ignore')
                    if response_text:
                        logging.info(f"Received from {client_addr}: {response_text}")
        except ConnectionResetError:
            logging.warning(f"Connection reset by {client_addr}")
        except socket.timeout:
            logging.warning(f"Timeout for client {client_addr}")
        except Exception as e:
            logging.error(f"Error in client thread {client_addr}: {e}")
        finally:
            if self.client_socket:
                self.client_socket.close()
                logging.info(f"Connection closed with {client_addr}")


def input_thread(chat_server):
    while True:
        message = input("Enter message to send or 'bye' to exit: ")
        chat_server.input_queue.put(message)
        if message == "bye":
            break


if __name__ == "__main__":
    server = ChatServer()
    input_thread_server = threading.Thread(target=input_thread, args=(server,))
    input_thread_server.start()
    server.start()
